package com.baihui.taobao.authorize;

import com.taobao.api.internal.util.StringUtils;
import com.taobao.api.internal.util.codec.Base64;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Kevin.
 * User: HSZM1106-0312
 * Date: 11-12-26
 * Time: 下午9:13
 */
public class TaoBaoCallBackUrlMgt {
    private String appKey;
    //上下文参数
    private String appParam;
    private String topSession;
    private String topSign;
    private String appSecret;
    private Map<String, String> paramMap;
    private TaoBaoSessionInfo taobaoSession;
    private TopParameter topParameter;

    public TaoBaoCallBackUrlMgt(String appKey, String appParams, String topSession, String topSign, String appSecret) {
        this.appKey = appKey;
        this.appParam = appParams;
        this.topSession = topSession;
        this.topSign = topSign;
        this.appSecret = appSecret;
    }


    public TaoBaoSessionInfo getTaoBaoSessionInfo() {
        if (taobaoSession == null) {
            taobaoSession = new TaoBaoSessionInfo(appKey, topParameter, topSession, appSecret,null,null, null);
        }
        return taobaoSession;
    }


    /**
     * 验证签名
     *
     * @param sign
     * @param parameter
     * @param secret
     * @return
     * @throws Exception
     */
    private static boolean validateSign(String sign, String parameter, String secret) throws Exception {
        // 对参数+密钥做MD5运算
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new Exception(e);
        }
        byte[] digest = md.digest((parameter).getBytes());

        // 对运算结果做BASE64运算并加密
        BASE64Encoder encode = new BASE64Encoder();
        String tmpSign = encode.encode(digest);

        return sign != null && secret != null && sign.equals(tmpSign);
        //注意，这个parameter并不就是上面的top_paramater，而是指的待签名验证的参数，即上面的top_appkey+top_parameter+top_session
    }

    /**
     * 得到参数值
     *
     * @param paramName
     * @return
     */
    private String getParamValue(String paramName) throws Exception {
        if (paramMap == null) {
            try {
                paramMap = decodeTopParams(appParam);
            } catch (IOException e) {
                throw new Exception(e);
            }
        }
        if (paramMap != null) {
            return paramMap.get(paramName);
        }
        return null;
    }

    public Map<String, String> decodeTopParams(String topParams) throws IOException {
        if (StringUtils.isEmpty(topParams)) {
            return null;
        }
        return convertBase64StringtoMap(topParams);

    }

    public Map<String, String> convertBase64StringtoMap(String str) {
        if (str == null)
            return null;
        String keyvalues = null;
        try {
            keyvalues = new String(Base64.decodeBase64(str.getBytes("gbk")), "gbk");
//            keyvalues = new String(Base64.decodeBase64(str.getBytes("utf-8")), "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String[] keyvalueArray = keyvalues.split("\\&");
        Map<String, String> map = new HashMap<String, String>();
        for (String keyvalue : keyvalueArray) {
            String[] s = keyvalue.split("\\=");
            if (s == null || s.length != 2)
                return null;
            map.put(s[0], s[1]);
        }
        return map;
    }


    /**
     * 校验合法性
     *
     * @return
     */
    public boolean verify() throws Exception {
        //.验证签名是否合法
        StringBuilder sb = new StringBuilder();
        sb.append(appKey).append(appParam).append(topSession).append(appSecret);
        boolean ret = validateSign(topSign, sb.toString(), appSecret);
        if (ret) {
            populateTopParameter();
            ret = validateTimestamp();
        }
        return ret;
    }

    /**
     * 验证时间戳是否在应用允许的误差范围
     * 5分钟以内，最长不超过30分钟。
     */
    private boolean validateTimestamp() {
        long ts = topParameter.getTs();
        long diff = System.currentTimeMillis() - ts;
        return diff < 30l * 60l * 1000l;
    }

    private void populateTopParameter() throws Exception {
        topParameter = new TopParameter();
        topParameter.setTs(Long.valueOf(getParamValue("ts")));
        topParameter.setIframe(getParamValue("iframe"));
        topParameter.setVisitor_id(Integer.parseInt(getParamValue("visitor_id")));
        topParameter.setVisitor_nick(getParamValue("visitor_nick"));
        topParameter.setVisitor_role(getParamValue("visitor_role"));
        if (getParamValue("expires_in") != null) {
            topParameter.setExpires_in(Long.valueOf(getParamValue("expires_in")));
        }
        if (getParamValue("re_expires_in") != null) {
            topParameter.setRe_expires_in(Long.valueOf(getParamValue("re_expires_in")));
        }

        if (getParamValue("sub_taobao_user_id") != null)
            topParameter.setSub_visitor_id(Integer.parseInt(getParamValue("sub_taobao_user_id")));
        topParameter.setSub_visitor_nick(getParamValue("sub_taobao_user_nick"));
    }


}
